/*
 * REFSocketAddress.h
 *
 *  Created on: Apr 14, 2013
 *      Author: Lucifer
 */

#ifndef REFNETWORKADDRESS_H_
#define REFNETWORKADDRESS_H_

namespace BFX
{

/**
 * Represents a generic interface to identify network addresses
 */
class REFSocketAddress : public REFObject
{
public:
	/**
	 * Gets the pointer and length to the raw SOCKADDR structure.
	 * @param[out] nSockAddrLen The length of the SOCKADDR structure, in bytes.
	 * @return The pointer of the SOCKADDR structure that contains the address to assign to this object.
	 */
	virtual const SOCKADDR* GetSockAddr( int& nSockAddrLen) const = 0;

	/**
	 * Creates a new instance of the BFX::REFSocketAddress class from a SOCKADDR structure.
	 * @param[in] pSockAddr A pointer to a SOCKADDR structure that contains the address to assign to.
	 * @param[in] nSockAddrLen The length of the address in pSockAddr in bytes.
	 * @return A new BFX::REFSocketAddress instance that is initialized from the specified SOCKADDR structure.
 	 */
	virtual REFSocketAddress* Create(const SOCKADDR* pSockAddr, int nSockAddrLen) const = 0;

	/**
	 * Gets the Internet Protocol (IP) address family.
	 * @return Should be SocketAddressFamily_InterNetwork.
	 */
	virtual SocketAddressFamily GetAddressFamily() const = 0;
};

/**
 * Represents a network address as an IP address and a port number.
 */
class REFInternetAddress : public REFSocketAddress
{
public:
	//
	// Constructions
	//

	/**
	 * Initializes a new instance of the BFX::REFInternetAddress class with the specified address and port number.
	 * @param[in] strAddress The network address, a dotted number such as "127.0.0.1".
	 *	Passing the empty string for this parameter indicates the socket should listen for client activity on all network interfaces.
	 * @param[in] nPort The port identifying the socket application.
	 */
	REFInternetAddress(const String& strAddress, int nPort);

	/**
	 * Initializes a new instance of the BFX::REFInternetAddress class with the specified address and port number.
	 * @param[in] pSockAddr A pointer to a SOCKADDR structure that contains the address to assign to this object.
	 * @param[in] nSockAddrLen The length of the address in pSockAddr in bytes.
	 */
	REFInternetAddress(const SOCKADDR* pSockAddr, int nSockAddrLen);

	/**
	 * Destroys the instance of the REFInternetAddress class.
	 */
	virtual ~REFInternetAddress();

	//
	// Attributes
	//

	/**
	 * Gets the IP address.
	 * @return A string that containing the IP address.
	 */
	String GetAddress() const;

	/**
	 * Sets the IP address.
	 * @param[in] strAddress A string that containing the IP address.
	 */
	void SetAddress(const String& strAddress);

	/**
	 * Gets the port number
	 * @return An integer value in the range 0x00000000 to 0x0000FFFF indicating the port number.
	 */
	int GetPort() const;

	/**
	 * Sets the port number
	 * @param[in] nPort An integer value in the range 0x00000000 to 0x0000FFFF indicating the port number.
	 */
	void SetPort(int nPort);

	//
	// REFSocketAddress overrides
	//

	/**
	 * Gets the Internet Protocol (IP) address family.
	 * @return Should be SocketAddressFamily_InterNetwork.
	 */
	virtual SocketAddressFamily GetAddressFamily() const;

	/**
	 * Gets the pointer and length to the raw SOCKADDR structure.
	 * @param[out] nSockAddrLen The length of the SOCKADDR structure, in bytes.
	 * @return The pointer of the SOCKADDR structure that contains the address to assign to this object.
	 */
	virtual const SOCKADDR* GetSockAddr( int& nSockAddrLen) const;

	/**
	 * Creates a new instance of the BFX::REFSocketAddress class from a SOCKADDR structure.
	 * @param[in] pSockAddr A pointer to a SOCKADDR structure that contains the address to assign to.
	 * @param[in] nSockAddrLen The length of the address in pSockAddr in bytes.
	 * @return A new BFX::REFSocketAddress instance that is initialized from the specified SOCKADDR structure.
 	 */
	virtual REFSocketAddress* Create(const SOCKADDR* pSockAddr, int nSockAddrLen) const;

	//
	// REFObject overrides
	//

	/**
	 * Determine whether the object of SocketAddress is valid; or not.
	 * @return The boolean value that indicates the valid state.
	 */
	bool IsValid() const;

private:
	// The helper method uses to invalidate our cache data, when address or port number been updated.
	void InvalidateCache() const;

public:
	// Lower / upper limits of port number.
	static const int MIN_PORT = 0x00000000;
	static const int MAX_PORT = 0x0000FFFF;

private:
	String	m_strAddress;
	int		m_nPort;

	// our buffered data.
	mutable BYTE*	m_pSockAddr;
	mutable int		m_nSockAddrLen;

	// the last error state of failed operations.
	mutable SocketError	m_lastError;
};

} /* namespace BFX */

#endif /* REFNETWORKADDRESS_H_ */
